package com.caius.xiaohashu.auth.service.Impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.caius.framework.biz.context.holder.LoginUserContextHolder;
import com.caius.framework.common.exception.BizException;
import com.caius.framework.common.response.Response;
import com.caius.xiaohashu.auth.constant.RedisKeyConstants;
import com.caius.xiaohashu.auth.enums.LoginTypeEnum;
import com.caius.xiaohashu.auth.enums.ResponseCodeEnum;
import com.caius.xiaohashu.auth.model.vo.user.UpdatePasswordReqVO;
import com.caius.xiaohashu.auth.model.vo.user.UserLoginReqVO;
import com.caius.xiaohashu.auth.rcp.UserRcpService;
import com.caius.xiaohashu.auth.service.AuthService;
import com.caius.xiaohashu.user.api.UserFeignApi;
import com.caius.xiaohashu.user.dto.resp.FindUserByPhoneRspDTO;
import com.google.common.base.Preconditions;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Objects;

/**
 * @author Caius
 * @description
 * @since Created in 2025-05-10
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private UserFeignApi userFeignApi;

    @Resource
    private UserRcpService userRcpService;

    /**
     * 登录与注册
     * @param userLoginReqVO
     * @return
     */
    @Override
    public Response<String> loginAndRegister(UserLoginReqVO userLoginReqVO) {
        String phone = userLoginReqVO.getPhone();
        Integer type = userLoginReqVO.getType();

        LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);

        Long userId = null;

        switch (loginTypeEnum){
            case VERIFICATION_CODE :
                String verificationCode = userLoginReqVO.getCode();

                Preconditions.checkArgument(StringUtils.isNotBlank(verificationCode), "验证码不能为空");

                String key = RedisKeyConstants.buildVerificationCodeKey(phone);
                String sentCode = (String) redisTemplate.opsForValue().get(key);

                if (!StringUtils.equals(verificationCode, sentCode)) {
                    throw new BizException(ResponseCodeEnum.VERIFICATION_CODE_ERROR);
                }

                // RCP : 调用用户服务，注册用户信息
                Long userIdTmp = userRcpService.registerUser(phone);

                if (Objects.isNull(userIdTmp)) {
                    throw new BizException(ResponseCodeEnum.LOGIN_FAIL);
                }

                userId = userIdTmp;
                break;
            case PASSWORD:
                String password = userLoginReqVO.getPassword();

                // RCP ： 调用用户服务，通过手机号查询用户信息
                FindUserByPhoneRspDTO findUserByPhoneRspDTO = userRcpService.findUserByPhone(phone);

                if (Objects.isNull(findUserByPhoneRspDTO)) {
                    throw new BizException(ResponseCodeEnum.USER_NOT_FOUND);
                }
                // 加密密码
                String encodePassword = findUserByPhoneRspDTO.getPassword();

                boolean isPasswordCorrect = passwordEncoder.matches(password, encodePassword);

                if (!isPasswordCorrect) {
                    throw new BizException(ResponseCodeEnum.VERIFICATION_CODE_SEND_FREQUENTLY);
                }

                userId = findUserByPhoneRspDTO.getId();
                break;
            default:
                break;
        }
        // SaToken 登录用户，并返回 token 令牌
        StpUtil.login(userId);

        // 获取 token 令牌
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        return Response.success(tokenInfo.tokenValue);
    }

    /**
     * 退出登录
     * @return
     */
    @Override
    public Response<?> logout() {
        Long userId = LoginUserContextHolder.getUserId();

        log.info("==> 用户退出登录， userId:{}", userId);

        StpUtil.logout(userId);

        return Response.success();
    }

    /**
     * 修改密码
     * @param updatePasswordReqVO
     * @return
     */
    @Override
    public Response<?> updatePassword(UpdatePasswordReqVO updatePasswordReqVO) {
        // 新密码
        String newPassword = updatePasswordReqVO.getNewPassword();
        // 加密密码
        String encodePassword = passwordEncoder.encode(newPassword);

        // RCP : 调用用户服务，更新密码
        userRcpService.updatePassword(encodePassword);

        return Response.success();
    }

    /**
     * 系统自动注册用户
     * @param phone
     * @return
     */
    public Long registerUser(String phone) {
        // RCP : 调用用户服务，用户注册
        Long userId = userRcpService.registerUser(phone);

        return userId;
    }
}
